package com.suoluo.zenadmin.http;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.log4j.Logger;

public final class HttpClientProxy {

	private static Logger logger = Logger.getLogger(HttpClientProxy.class);
	private final HttpClient client;

	private final MultiThreadedHttpConnectionManager connectionManager;
	
	//每个主机支持的并行连接数
	private final int maxHostConnections = 32;
	//客户端支持的最大连接数
	private final int maxTotalConnections = 150;
	private final int connectionTimeout = 5000;
	private final int soTimeout = 3000;
	
	private static HttpClientProxy instance;
	

//	public HttpImporter() {
//		// change timeout to 2s avoid block thread-pool (Tim)
////		this(150, 2000, 2000, 1024 * 1024);
//	}

	private HttpClientProxy() {
		connectionManager = new MultiThreadedHttpConnectionManager();
		HttpConnectionManagerParams params = connectionManager.getParams();
		params.setDefaultMaxConnectionsPerHost(maxHostConnections);
		params.setMaxTotalConnections(maxTotalConnections);
		params.setConnectionTimeout(connectionTimeout);
		params.setSoTimeout(soTimeout);

		HttpClientParams clientParams = new HttpClientParams();
		// 忽略cookie 避免 Cookie rejected 警告
		clientParams.setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
		client = new HttpClient(clientParams,
				connectionManager);
		Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);
		Protocol.registerProtocol("https", myhttps);
		// 支持proxy
//		if (proxyHost != null && !proxyHost.equals("")) {
//			client.getHostConfiguration().setProxy(proxyHost, proxyPort);
//			client.getParams().setAuthenticationPreemptive(true);
//			if (proxyAuthUser != null && !proxyAuthUser.equals("")) {
//				client.getState().setProxyCredentials(
//						AuthScope.ANY,
//						new UsernamePasswordCredentials(proxyAuthUser,
//								proxyAuthPassword));
//				log("Proxy AuthUser: " + proxyAuthUser);
//				log("Proxy AuthPassword: " + proxyAuthPassword);
//			}
//		}
	}
	
	public static HttpClientProxy getInstance(){
		synchronized (HttpClientProxy.class) {
			if (instance ==  null){
				instance = new HttpClientProxy();
			}
			return instance;
		}
	}
	
	private HttpResponse doRequest(HttpMethod method){
		try{
			//设置重连机制
			method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,new DefaultHttpMethodRetryHandler());
			method.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "utf-8");
			int statusCode = client.executeMethod(method);
			return new HttpResponse(statusCode, method.getResponseBodyAsString());
		} catch (HttpException e) {
			logger.error("", e);
			throw new com.suoluo.zenadmin.http.HttpException(e);
		} catch (IOException e) {
			logger.error("", e);
			throw new com.suoluo.zenadmin.http.HttpException(e);
		}finally{
			method.releaseConnection();
		}
	}
	
	
	
	/*
	 * 对parameters进行encode处理
	 */
	public static String encodeParameters(List<NameValuePair> params) {
		StringBuffer buf = new StringBuffer();

		if (params != null){
			int index = 0;
			for (NameValuePair param : params) {
				if (index != 0) {
					buf.append("&");
				}
				try {
					buf.append(URLEncoder.encode(param.getName(), "UTF-8"))
							.append("=")
							.append(URLEncoder.encode(param.getValue(), "UTF-8"));
				} catch (java.io.UnsupportedEncodingException neverHappen) {
				}
				index++;
			}
		}
		return buf.toString();
	}
	public HttpResponse get(String url){
		 GetMethod method = new GetMethod(url);
		 return doRequest(method);
	}
	
	public HttpResponse get(String url, List<NameValuePair> params) {
		// log("Request:");
		// log("GET:" + url);
		String encodedParams = encodeParameters(params);
		if (-1 == url.indexOf("?")) {
			url += "?" + encodedParams;
		} else {
			url += "&" + encodedParams;
		}
		GetMethod method = new GetMethod(url);
		return doRequest(method);
	}
	
	public HttpResponse post(String url,List<NameValuePair> params){
		PostMethod method = new PostMethod(url);
//		for (int i = 0; i < params.length; i++) {
//			postMethod.addParameter(params[i].getName(), params[i].getValue());
//		}
		
		method.setRequestBody(params.toArray(new NameValuePair[0]));
		HttpMethodParams param = method.getParams();
		param.setContentCharset("UTF-8");
		return doRequest(method);
	}
	
	public HttpResponse post(String url,String json){
		PostMethod method = new PostMethod(url);
		try {
			RequestEntity entity = new StringRequestEntity(json, "application/json", "UTF-8");
			method.setRequestEntity(entity);
			HttpMethodParams param = method.getParams();
//			param.setContentCharset("UTF-8");
			return doRequest(method);
		} catch (UnsupportedEncodingException e) {
			throw new com.suoluo.zenadmin.http.HttpException(e);
		}
	}
}
